package com.websocket;

import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;

import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;

import com.alibaba.fastjson.JSONObject;
@ServerEndpoint(value="/chat.ws")
public class ChatAction {
	/**
	 * <Long, <Long, <String, ChatAction>>> : <sender, <receiver, <sessionId, chatAction>>>
	 */
	private static Map<Long, Map<Long, Map<String, ChatAction>>> chatMaps = new ConcurrentHashMap<Long, Map<Long, Map<String, ChatAction>>>();
    private Session session;
    private long sender = 0;
    private long receiver = 0;
    //调用new WebSocket时触发
    @OnOpen
    public void start(Session session) {
        System.out.println("start");
        this.session = session;
        Map<String, List<String>> map = session.getRequestParameterMap();
        
        if(!senderAuth(map)){
        	System.out.println("用户［id="+sender+"］无权限发起聊天");
        	sender = 0;
        	return;
        }
        receiver = Long.parseLong(map.get("r")!=null?map.get("r").get(0):"0");
        boolean reConnect = map.get("rc")!=null;
        Map<Long, Map<String, ChatAction>> chatMap = chatMaps.get(sender);
        if(chatMap!=null){
        	Map<String, ChatAction> chat = chatMap.get(receiver);
        	if(chat!=null && !reConnect){	//保持一对用户之间只有一个存活的即时通讯窗口
            	broadcastSystemMsg(sender, receiver, "您已经新开了聊天窗口，当前聊天窗口将断开", true);
            	chatMap.remove(receiver);
        	}
        }else{
        	chatMap = new HashMap<Long, Map<String, ChatAction>>();
        }
        Map<String, ChatAction> tmp = new HashMap<String, ChatAction>();
        tmp.put(session.getId(), this);
        chatMap.put(receiver, tmp);
        chatMaps.put(sender, chatMap);
        System.out.println(session.getId() + " join chat live");
    }
 
    /**
     * 验证sender权限
     * @param map
     * @return
     */
    private boolean senderAuth(Map<String, List<String>> map){
        String code = map.get("co")!=null?map.get("co").get(0):null;
        if(code==null){
            return false;
        }
        sender = Long.parseLong(map.get("s")!=null?map.get("s").get(0):"0");
        if(sender<=0){
            return false;
        }
        return true;
    }
    
    @OnClose
    public void end() {
    	Map<Long, Map<String, ChatAction>> chatMap = chatMaps.get(sender);
    	if(chatMap==null){
    		return;
    	}
    	Map<String, ChatAction> map = chatMap.get(receiver);
    	if(map!=null && map.get(session.getId())!=null){	//需要通过sessionId来校验该聊天窗口是否真的需要销毁，避免误删
    		chatMap.remove(receiver);
        	System.out.println(session.getId() + " leave chat live");
    	}
    }
 
    private static ChatAction getChatByKey(long sender, long receiver){
    	Map<Long, Map<String, ChatAction>> chatMap = chatMaps.get(sender);
    	if(chatMap==null){
    		return null;
    	}
    	Map<String, ChatAction> map = chatMap.get(receiver);
    	if(map==null){
    		return null;
    	}
    	return (ChatAction)map.values().toArray()[0];
    }
    @OnMessage
    public void incoming(String message) {
    	ChatAction client = getChatByKey(sender,receiver);//获取receiver的client
        sendMsg2Client("你好啊", client, "system", false);
    }
 
    @OnError
    public void onError(Throwable t) throws Throwable {
        System.out.println("Chat Error: " + t.getMessage());
    }
    
    /**
     * 外部调用的消息广播
     * @param msgId
     * @param twoSides
     */
    // public static void broadcast(long msgId, byte source, boolean twoSides) {
    // 	ChatAction client = getChatByKey(receiver, sender);//获取receiver的client
    // 	sendMsg2Client("hehe", client, "you");	//给接收者推送消息
    //     System.out.println("broadcast");
    // }
    
    public static void broadcastSystemMsg(long sender, long receiver, String content, boolean disconnect) {
        System.out.println("broadcastSystemMsg");
    	ChatAction client = getChatByKey(receiver, sender);//获取receiver的client
    	sendMsg2Client(content, client, "system", disconnect);
    }
    
    private static void sendMsg2Client(String content, ChatAction client, String senderCode){
    	sendMsg2Client(content, client, senderCode, false);
    }
    
    private static void sendMsg2Client(String content, ChatAction client, String senderCode, boolean disconnect){
    	if(client!=null){
    		synchronized (client) {
		    	try {
					JSONObject obj = new JSONObject();
					obj.put("content", content);
					obj.put("sender", senderCode);
					obj.put("disconnect", disconnect);
					client.session.getBasicRemote().sendText(obj.toJSONString());
				} catch (IOException e) {
					e.printStackTrace();
				}
    		}
    	}
    }
}
